package com.mlx.permission.row;

import com.mlx.permission.entity.RowPermission;
import com.mlx.permission.inter.Validator;

import java.util.Collection;
import java.util.Map;
import java.util.Set;

/**
 * 行权限验证器：
 *     确定行权限的容器为Map类型（双重Map）
 * @param <P> 行权限实体类型
 */
public interface IRowValidator<P extends RowPermission> extends Validator<P, Map<String, Map<String, Set<String>>>> {

    /**
     * 判断当前实体是否拥有数据【data】的权限，必须指出数据【data】属于哪张表，如果数据表有外键并且该外键也被用做权限控制，也要指出外键字段信息
     * @param data 数据对象
     * @param tableName 数据所属表名称
     * @param foreignKeys 外键表达式列表，用于指定本表外键字段引用自哪张表的哪个字段，外键表达式必须符合特定的格式
     *                    外键表达式格式：本表字段名称:外表表名称:外表字段名称；
     *                        三个元素以“:”相隔；元素名称必须符合java变量命名规范
     *
     * @return 布尔值
     */
    boolean isHavePermission(Object data, String tableName, String[] foreignKeys);

    default boolean isNotHavePermission(Object data, String tableName, String[] foreignKeys){
        return !isHavePermission(data, tableName, foreignKeys);
    }

    /**
     * 功能类似【boolean isHavePermission(Object data, String tableName, String[] foreignKeys)】
     *
     * 用于判断非实体类类型、类似Map类型的数据的数据权限
     *
     */
    boolean isHavePermission(Object data, String tableName, String[] foreignKeys, String getterName, String setterName, String fieldSetMethodName);

    default boolean isNotHavePermission(Object data, String tableName, String[] foreignKeys, String getterName, String setterName, String fieldSetMethodName){
        return !isHavePermission(data, tableName, foreignKeys, getterName, setterName, fieldSetMethodName);
    }

    /**
     * 行过滤方法：清理数据集合【dataList】中不属于当前实体权限范围内的数据
     *
     * @param dataCollection 数据集合
     * @param tableName 表名称
     * @param foreignKeys 外键表达式列表
     */
    void rowFilter(Collection<?> dataCollection, String tableName, String[] foreignKeys);

    /**
     * 行过滤方法：清理数据集合【dataList】中不属于当前实体权限范围内的数据，支持类似Map类型的数据
     *
     */
    void rowFilter(Collection<?> dataCollection, String tableName, String[] foreignKeys, String getterName, String setterName, String fieldSetMethodName);

}
